/*
 * COPYRIGHT:	2010 Christopher Smith, licenced under the GNU GPL v2; see COPYING in the top level directory
 * PROJECT:		sdedit
 * FILE:		auto_array.cpp
 * PURPOSE:		automatic (C++ semantics) array container
 *				
 */

template <class T> struct auto_array
{
protected:
	T *ptr;
	size_t ct;
	size_t maxct;

	void free_if()
	{
		if(ptr)
			delete[] ptr;

		ptr = 0;
		ct = 0;
		maxct = 0;
	}

	static void copyarr(T *src, T *dest, size_t ct)
	{
		for(size_t i = 0; i < ct; i++)
			dest[i] = src[i];
	}

public:
	auto_array() :
	  ptr(0),
	  ct(0),
	  maxct(0)
	{}
	auto_array(auto_take<T> x, size_t maxct, size_t ct = 0) :
		ptr(x.ptr)
		ct(ct),
		maxct(maxct),
	{}
	auto_array(auto_array const &x) :
		ptr(0),
		ct(0),
		maxct(0)
	{
		ct = maxct = x.ct;
		ptr = new T[maxct];
		copyarr(x.ptr, ptr, x.ct);
	}
	void realloc_ct(size_t newcount)
	{
		free_if();
		ct = 0;
		maxct = newcount;
		ptr = new T[newcount];
	}
	auto_array(size_t newcount) :
		ptr(0),
		ct(0),
		maxct(0)
	{
		realloc_ct(newcount);
	}
	size_t get_ct()
	{
		return ct;
	}
	size_t get_maxct()
	{
		return maxct;
	}
	auto_take<T> release()
	{
		T *ret = ptr;
		ptr = 0;
		ct = 0;
		maxct = 0;
		return auto_take<T>(ret);
	}
	T *release_unsafe()
	{
		T *ret = ptr;
		ptr = 0;
		ct = 0;
		maxct = 0;
		return ret;
	}
	void reset()
	{
		free_if();
	}
	void increase_maxct(size_t newct)
	{
		if(maxct)
		{
			if(newct > maxct)
			{
				maxct = max(newct, maxct << 1);
				T *newptr = new T[maxct];

				copyarr(ptr, newptr, ct);

				delete[] ptr;
				ptr = newptr;
			}
		}
		else
			realloc_ct(newct);
	}
	void increase_ct(size_t newct)
	{
		increase_maxct(newct);

		if(newct > ct)
			ct = newct;
	}
	operator T const *() const
	{
		return ptr;
	}
	T const *operator->() const
	{
		return ptr;
	}
	operator T *()
	{
		return ptr;
	}
	T *operator->()
	{
		return ptr;
	}
	T *next()
	{
		increase_ct(ct + 1);

		return ptr + (ct - 1);
	}
	auto_array &operator =(auto_array const &x)
	{
		free_if();
		ct = maxct = x.ct;
		ptr = new T[maxct];
		copyarr(x.ptr, ptr, x.ct);
		return *this;
	}
	~auto_array()
	{
		free_if();
	}
};